package com.leetcode.code;

import java.util.concurrent.Semaphore;
import java.util.function.IntConsumer;

/**
 * Description:
 *
 * @author zkingcobra
 * Date: 2020/6/11 4:04 下午
 */
public class LeetCode1116Java {

    public static void main(String[] args) {
        //ExecutorService executorService = new ThreadPoolExecutor(3, 3, 0L, TimeUnit.MILLISECONDS,
        //        new LinkedBlockingQueue<>());

        ZeroEvenOdd zeroEvenOdd = new ZeroEvenOdd(5);

        //executorService.execute(new Runnable() {
        //    @Override public void run() {
        //
        //    }
        //});

        new Thread(() -> {
            try {
                zeroEvenOdd.zero(value -> System.out.println(value));
            } catch (Exception e) {
                e.printStackTrace();
            }
        }).start();

        new Thread(() -> {
            try {
                zeroEvenOdd.even(value -> System.out.println(value));
            } catch (Exception e) {
                e.printStackTrace();
            }
        }).start();

        new Thread(() -> {
            try {
                zeroEvenOdd.odd(value -> System.out.println(value));
            } catch (Exception e) {
                e.printStackTrace();
            }
        }).start();
    }

    static class ZeroEvenOdd {

        private final int n;
        Semaphore zeroSemaphore = new Semaphore(1);
        Semaphore oddSemaphore = new Semaphore(0);
        Semaphore evenSemaphore = new Semaphore(0);

        public ZeroEvenOdd(int n) {
            this.n = n;
        }

        // printNumber.accept(x) outputs "x", where x is an integer.
        public void zero(IntConsumer printNumber) throws Exception {
            boolean flag = true;
            for (int i = 0; i < n; i++) {
                //JLog.info(" zero " + i);
                zeroSemaphore.acquire();
                printNumber.accept(0);
                if (flag) {
                    oddSemaphore.release();
                    flag = false;
                } else {
                    evenSemaphore.release();
                    flag = true;
                }
            }
        }

        // 偶数
        public void even(IntConsumer printNumber) throws Exception {
            for (int i = 2; i <= n; i += 2) {
                //JLog.info(" even " + i);
                evenSemaphore.acquire();
                printNumber.accept(i);
                zeroSemaphore.release();
            }
        }

        // 奇数
        public void odd(IntConsumer printNumber) throws Exception {
            for (int i = 1; i <= n; i += 2) {
                //JLog.info(" odd " + i);
                oddSemaphore.acquire();
                printNumber.accept(i);
                zeroSemaphore.release();
            }
        }
    }
}
